﻿using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
using System.Data;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Web;
using Xwltz.Framework.Helper;

namespace Xwltz.Framework.Framework
{
    public static class CommonBase
    {
        public static readonly long Timestampbegin = new DateTime(1970, 1, 1, 0, 0, 0, 0).Ticks;
        public static List<string> Province = new List<string> { "北京市", "天津市", "上海市", "重庆市", "河北省", "山西省", "辽宁省", "吉林省", "黑龙江省", "江苏省", "浙江省", "安徽省", "福建省", "江西省", "山东省", "河南省", "湖北省", "湖南省", "广东省", "海南省", "四川省", "贵州省", "云南省", "陕西省", "甘肃省", "青海省", "广西壮族自治区", "内蒙古自治区", "西藏自治区", "宁夏回族自治区", "新疆维吾尔自治区", "香港", "澳门", "台湾" };
        public static List<string> ProvinceSimple = new List<string> { "北京", "天津", "上海", "重庆", "河北", "山西", "辽宁", "吉林", "黑龙江", "江苏", "浙江", "安徽", "福建", "江西", "山东", "河南", "湖北", "湖南", "广东", "海南", "四川", "贵州", "云南", "陕西", "甘肃", "青海", "广西", "内蒙古", "西藏", "宁夏", "新疆", "香港", "澳门", "台湾" };
        public static List<string> Source = new List<string> { "短信", "微博", "微信", "B2B", "百度", "搜狗", "360", "头条" };
        public static Dictionary<int, string> SourceWeight = new Dictionary<int, string> { { 6 , "短信" }, { 4, "微博" }, { 15, "微信" }, { 10, "B2B" }, { 25, "百度" }, { 18, "搜狗" }, { 12, "360" }, { 7, "头条" } };
        public static List<string> Phone10086 = new List<string> { "134", "135", "136", "137", "138", "139", "147", "148", "150", "151", "152", "157", "158", "159", "172", "178", "182", "183", "184", "187", "188", "198" };
        public static List<string> Phone10010 = new List<string> { "130", "131", "132", "145", "146", "155", "156", "166", "171", "175", "176", "185", "186" };
        public static List<string> Phone10000 = new List<string> { "133", "149", "153", "173", "174", "177", "180", "181", "189", "199" };
        public static List<string> Phone170 = new List<string> { "170" };
        public static List<string> ChineseName = new List <string> {"赵","钱","孙","李","周","吴","郑","王","冯","陈","褚","卫","蒋","沈","韩","杨","朱","秦","尤","许","何","吕","施","张","孔","曹","严","华","金","魏","陶","姜","戚","谢","邹","喻","柏","水","窦","章","云","苏","潘","葛","奚","范","彭","郎","鲁","韦","昌","马","苗","凤","花","方","俞","任","袁","柳","酆","鲍","史","唐","费","廉","岑","薛","雷","贺","倪","汤","滕","殷","罗","毕","郝","邬","安","常","乐","于","时","傅","皮","卞","齐","康","伍","余","元","卜","顾","孟","平","黄","和","穆","萧","尹","姚","邵","湛","汪","祁","毛","禹","狄","米","贝","明","臧","计","伏","成","戴","谈","宋","茅","庞","熊","纪","舒","屈","项","祝","董","梁","杜","阮","蓝","闵","席","季","麻","强","贾","路","娄","危","江","童","颜","郭","梅","盛","林","刁","钟","徐","邱","骆","高","夏","蔡","田","樊","胡","凌","霍","虞","万","支","柯","昝","管","卢","莫","经","房","裘","缪","干","解","应","宗","丁","宣","贲","邓","郁","单","杭","洪","包","诸","左","石","崔","吉","钮","龚","程","嵇","邢","滑","裴","陆","荣","翁","荀","羊","于","惠","甄","曲","家","封","芮","羿","储","靳","汲","邴","糜","松","井","段","富","巫","乌","焦","巴","弓","牧","隗","山","谷","车","侯","宓","蓬","全","郗","班","仰","秋","仲","伊","宫","宁","仇","栾","暴","甘","钭","厉","戎","祖","武","符","刘","景","詹","束","龙","叶","幸","司","韶","郜","黎","蓟","溥","印","宿","白","怀","蒲","邰","从","鄂","索","咸","籍","赖","卓","蔺","屠","蒙","池","乔","阴","郁","胥","能","苍","双","闻","莘","党","翟","谭","贡","劳","逄","姬","申","扶","堵","冉","宰","郦","雍","却","璩","桑","桂","濮","牛","寿","通","边","扈","燕","冀","浦","尚","农","温","别","庄","晏","柴","瞿","阎","充","慕","连","茹","习","宦","艾","鱼","容","向","古","易","慎","戈","廖","庾","终","暨","居","衡","步","都","耿","满","弘","匡","国","文","寇","广","禄","阙","东","欧","殳","沃","利","蔚","越","夔","隆","师","巩","厍","聂","晁","勾","敖","融","冷","訾","辛","阚","那","简","饶","空","曾","毋","沙","乜","养","鞠","须","丰","巢","关","蒯","相","查","后","荆","红","游","郏","竺","权","逯","盖","益","桓","公","仉","督","岳","帅","缑","亢","况","郈","有","琴","归","海","晋","楚","闫","法","汝","鄢","涂","钦","商","牟","佘","佴","伯","赏","墨","哈","谯","篁","年","爱","阳","佟","言","福","南","火","铁","迟","漆","官","冼","真","展","繁","檀","祭","密","敬","揭","舜","楼","疏","冒","浑","挚","胶","随","高","皋","原","种","练","弥","仓","眭","蹇","覃","阿","门","恽","来","綦","召","仪","风","介","巨","木","京","狐","郇","虎","枚","抗","达","杞","苌","折","麦","庆","过","竹","端","鲜","皇","亓","老","是","秘","畅","邝","还","宾","闾","辜","纵","侴","万俟","司马","上官","欧阳","夏侯","诸葛","闻人","东方","赫连","皇甫","羊舌","尉迟","公羊","澹台","公冶","宗正","濮阳","淳于","单于","太叔","申屠","公孙","仲孙","轩辕","令狐","钟离","宇文","长孙","慕容","鲜于","闾丘","司徒","司空","兀官","司寇","南门","呼延","子车","颛孙","端木","巫马","公西","漆雕","车正","壤驷","公良","拓跋","夹谷","宰父","谷梁","段干","百里","东郭","微生","梁丘","左丘","东门","西门","南宫","第五","公仪","公乘","太史","仲长","叔孙","屈突","尔朱","东乡","相里","胡母","司城","张廖","雍门","毋丘","贺兰","綦毋","屋庐","独孤","南郭","北宫","王孙"};
        public static List<string> ChineseNameOnly = new List <string> {"赵","钱","孙","李","周","吴","郑","王","冯","陈","卫","蒋","沈","韩","杨","朱","秦","尤","许","何","吕","施","张","孔","曹","严","华","金","魏","陶","姜","戚","谢","邹","章","苏","潘","葛","范","彭","鲁","韦","昌","马","苗","方","俞","任","袁","柳","鲍","史","唐","费","薛","雷","贺","倪","汤","殷","罗","毕","郝","常","时","傅","卞","齐","伍","余","顾","孟","黄","穆","萧","尹","姚","邵","汪","祁","毛","臧","计","成","戴","宋","庞","熊","纪","屈","项","祝","董","梁","杜","阮","闵","贾","江","童","颜","郭","梅","盛","林","刁","钟","徐","邱","骆","高","夏","蔡","田","樊","胡","凌","霍","管","卢","莫","房","裘","缪","干","解","丁","宣","邓","郁","单","杭","洪","包","诸","石","崔","吉","龚","程","邢","裴","陆","荣","翁","荀","于","甄","曲","封","芮","储","靳","糜","段","焦","山","侯","全","班","秋","仲","伊","宫","宁","仇","甘","厉","戎","祖","刘","詹","叶","幸","韶","郜","宿","白","蒲","邰","鄂","卓","蔺","池","乔","闻","莘","翟","谭","申","牛","燕","冀","浦","温","庄","瞿","阎","习","艾","古","易","廖","庾","居","衡","耿","满","匡","文","广","蔚","聂","冷","辛","简","曾","丰","关","蒯","荆","岳","晋","闫","涂","商"};
        public static string RootDomain = ".com.cn|.net.cn|.org.cn|.gov.cn|.com|.net|.cn|.org|.cc|.me|.tel|.mobi|.asia|.biz|.info|.name|.tv|.hk|.top|";
        private static readonly char[] Constant = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '!', '@', '#', '$', '%', '^', '&', '*', '|', '+', '(', ')' };
        private static readonly char[] NumberConstant = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' };

        #region 通用方法

        /// <summary>
        /// 默认值
        /// </summary>
        /// <param name="typename"></param>
        /// <returns></returns>
        public static object GetDefaultVal(string typename)
        {
            switch (typename)
            {
                case "Boolean":
                    return false;
                case "DateTime":
                    return DateTime.Now;
                case "Double":
                    return 0.0;
                case "Single":
                    return 0f;
                case "Int32":
                    return 0;
                case "String":
                    return "".ToTrims();
                case "Decimal":
                    return 0m;
            }
            return null;
        }

        /// <summary>
        /// 将实体类的所有字段为Null的替换成非空
        /// 提升实体类的可读性
        /// </summary>
        /// <typeparam name="TEntity"></typeparam>
        /// <param name="model"></param>
        public static void CoverNull<TEntity>(TEntity model) where TEntity : class, new()
        {
            if (model == null)
            {
                return;
            }
            var typeFromHandle = typeof(TEntity);
            var properties = typeFromHandle.GetProperties();
            var array = properties;
            foreach (var propertyInfo in array)
            {
                if (propertyInfo.GetValue(model, null) != null) continue;
                if (propertyInfo.GetCustomAttributes(typeof(NotMappedAttribute), false).Length <= 0)
                {
                    propertyInfo.SetValue(model, GetDefaultVal(propertyInfo.PropertyType.Name), null);
                }
            }
        }

        /// <summary>
        /// List to DataTable
        /// </summary>
        /// <typeparam name="TEntity"></typeparam>
        /// <param name="list"></param>
        /// <returns></returns>
        public static DataTable ListToTable<TEntity>(List<TEntity> list)
        {
            var table = new DataTable();
            var typeFromHandle = typeof(TEntity);
            var proinfos = typeFromHandle.GetProperties().ToList();
            proinfos.ForEach(delegate(PropertyInfo a)
            {
                table.Columns.Add(a.Name);
            });
            list.ForEach(delegate(TEntity model)
            {
                var row = table.NewRow();
                proinfos.ForEach(delegate(PropertyInfo info)
                {
                    object value = info.GetValue(model, null);
                    if (value == null)
                    {
                        row[info.Name] = string.Empty;
                        return;
                    }
                    row[info.Name] = value.ToString();
                });
                table.Rows.Add(row);
            });
            return table;
        }

        /// <summary>
        /// 返回最后一层错误信息
        /// </summary>
        /// <param name="ex"></param>
        /// <returns></returns>
        public static string LastInnerMessage(this Exception ex)
        {
            while (true)
            {
                LogHelper.ErrorTxt("", ex);
                if (ex.InnerException == null) return ex.Message;
                ex = ex.InnerException;
            }
        }

        /// <summary>
        /// 获取最新号段（2018-04）
        /// </summary>
        /// <returns></returns>
        public static List<string> PhoneNumber(out int count)
        {
            var list = Phone10086.Union(Phone10010).Union(Phone10000).Union(Phone170).ToList();
            count = list.Count;
            return list;
        }

        #endregion

        #region Stopwatch计时器
        /// <summary>
        /// 计时器开始
        /// </summary>
        /// <returns></returns>
        public static Stopwatch TimerStart()
        {
            var watch = new Stopwatch();
            watch.Reset();
            watch.Start();
            return watch;
        }
        /// <summary>
        /// 计时器结束
        /// </summary>
        /// <param name="watch"></param>
        /// <returns></returns>
        public static string TimerEnd(Stopwatch watch)
        {
            watch.Stop();
            double costtime = watch.ElapsedMilliseconds;
            return costtime.ToString(CultureInfo.InvariantCulture);
        }
        #endregion

        #region 删除数组中的重复项
        /// <summary>
        /// 删除数组中的重复项
        /// </summary>
        /// <param name="values"></param>
        /// <returns></returns>
        public static string[] RemoveDup(string[] values)
        {
            var list = new List<string>();
            foreach (var t in values)
            {
                if (!list.Contains(t))
                {
                    list.Add(t);
                }
            }
            return list.ToArray();
        }
        #endregion

        #region 自动生成编号
        /// <summary>
        /// 表示全局唯一标识符 (GUID)。
        /// </summary>
        /// <returns></returns>
        public static string GuId()
        {
            return Guid.NewGuid().ToString().ToUpper();
        }

        /// <summary>
        /// 表示全局唯一标识符 (GUID)。
        /// </summary>
        /// <returns></returns>
        public static string GuId(bool flag)
        {
            return Guid.NewGuid().ToString("N").ToUpper();
        }

        public static Guid GenerateGuid()
        {
            var guidArray = Guid.NewGuid().ToByteArray();

            var baseDate = new DateTime(1900, 1, 1);
            var now = DateTime.Now;
            var days = new TimeSpan(now.Ticks - baseDate.Ticks);
            var msecs = now.TimeOfDay;

            var daysArray = BitConverter.GetBytes(days.Days);
            var msecsArray = BitConverter.GetBytes((long)(msecs.TotalMilliseconds / 3.333333));

            Array.Reverse(daysArray);
            Array.Reverse(msecsArray);

            Array.Copy(daysArray, daysArray.Length - 2, guidArray, guidArray.Length - 6, 2);
            Array.Copy(msecsArray, msecsArray.Length - 4, guidArray, guidArray.Length - 4, 4);

            return new Guid(guidArray);
        }  

        /// <summary>
        /// 自动生成编号  201008251145409865
        /// </summary>
        /// <returns></returns>
        public static string CreateNo()
        {
            var random = new Random(Guid.NewGuid().GetHashCode());
            var strRandom = random.Next(0, 10000).ToString(); //生成编号 
            var code = DateTime.Now.ToString("yyyyMMddHHmmss") + strRandom;//形如
            return code;
        }

        /// <summary>
        /// 生成订单编号，加锁
        /// </summary>
        private static readonly object NumberObj = new object();
        public static string CreateOrderNo()
        {
            lock (NumberObj)
            {
                var number = new[] { DateTime.Now.ToString("yyMMddHHmmssfff"), RndNum(5).ToString().PadLeft(5, '0') };
                //var random = number.OrderBy(x => Guid.NewGuid());
                var no = number.Select(x => "" + x + "");
                var strNumber = string.Join("", no.ToArray());
                return strNumber;
            }
        }

        #endregion

        #region 生成随机数

        /// <summary>
        /// 生成0-9随机数
        /// </summary>
        /// <param name="codeNum">生成长度</param>
        /// <param name="start">开始值</param>
        /// <param name="end">结束值</param>
        /// <returns></returns>
        public static int RndNum(int codeNum, int start = 0,int end = 9)
        {
            var sb = new StringBuilder(codeNum);
            var rand = new Random(Guid.NewGuid().GetHashCode());
            for (var i = 0; i < codeNum; i++)
            {
                var t = rand.Next(start, end);
                sb.AppendFormat("{0}", t);
            }
            return sb.ToString().ToInt();
        }

        /// <summary>
        /// 生成指定随机数（长度1）
        /// </summary>
        /// <param name="start">开始值</param>
        /// <param name="end">结束值</param>
        /// <returns></returns>
        public static int RandomNumber(int start = 1, int end = 10)
        {
            var rand = new Random(Guid.NewGuid().GetHashCode()).Next(start, end + 1);
            return rand;
        }

        /// <summary>
        /// 生成数字
        /// </summary>
        /// <param name="maxValue"></param>
        /// <returns></returns>
        public static int AutoNumber(int maxValue)
        {
            var rd = new Random(Guid.NewGuid().GetHashCode());
            return rd.Next(maxValue);
        }

        /// <summary>
        /// 生成自定义字符串
        /// </summary>
        /// <param name="length"></param>
        /// <returns></returns>
        public static string AutoStr(int length)
        {
            var newRandom = new StringBuilder(74);
            var rd = new Random(Guid.NewGuid().GetHashCode());
            for (var i = 0; i < length; i++)
            {
                newRandom.Append(Constant[rd.Next(74)]);
            }
            return newRandom.ToString();
        }

        #endregion

        #region 删除最后一个字符之后的字符
        /// <summary>
        /// 删除最后结尾的一个逗号
        /// </summary>
        public static string ToDelLastComma(this string str, string tip = ",")
        {
            return str.Substring(0, str.LastIndexOf(tip, StringComparison.Ordinal));
        }
        /// <summary>
        /// 删除最后结尾的指定字符后的字符
        /// </summary>
        public static string DelLastChar(string str, string strchar)
        {
            return str.Substring(0, str.LastIndexOf(strchar, StringComparison.Ordinal));
        }
        /// <summary>
        /// 删除最后结尾的长度
        /// </summary>
        /// <param name="str"></param>
        /// <param name="length"></param>
        /// <returns></returns>
        public static string DelLastLength(string str, int length)
        {
            if (string.IsNullOrEmpty(str))
                return "";
            str = str.Substring(0, str.Length - length);
            return str;
        }
        #endregion

        #region 获取上传文件的后缀名 并返回GUID的新文件名

        /// <summary>
        /// 获取上传文件的后缀名 并返回GUID的新文件名
        /// </summary>
        /// <param name="file"></param>
        /// <param name="filetype"></param>
        /// <returns></returns>
        public static string GetFileName(HttpPostedFileBase file, string filetype = "img")
        {
            var ext = file.FileName.GetSuffixName(true);
            return Guid.NewGuid().ToString("N") + ext;
        }

        #endregion

        #region 设置数据表默认值

        /// <summary>
        /// 设置新增相关数据
        /// </summary>
        /// <param name="model"></param>
        /// <param name="currentUserId"></param>
        public static void SetCreateField(object model, string currentUserId)
        {
            var type = model.GetType();
            var pinfos = type.GetProperties();
            if (pinfos.Any(a => a.Name.Equals("CreatedBy")))
            {
                var info = pinfos.FirstOrDefault(a => a.Name.Equals("CreatedBy"));
                if (info != null) info.SetValue(model, currentUserId, null);
            }
            if (pinfos.Any(a => a.Name.Equals("CreatedTime")))
            {
                var info = pinfos.FirstOrDefault(a => a.Name.Equals("CreatedTime"));
                if (info != null) info.SetValue(model, DateTime.Now, null);
            }
            if (pinfos.Any(a => a.Name.Equals("CreateBy")))
            {
                var info = pinfos.FirstOrDefault(a => a.Name.Equals("CreateBy"));
                if (info != null) info.SetValue(model, currentUserId, null);
            }
            if (pinfos.Any(a => a.Name.Equals("CreateTime")))
            {
                var info = pinfos.FirstOrDefault(a => a.Name.Equals("CreateTime"));
                if (info != null) info.SetValue(model, DateTime.Now, null);
            }
        }

        /// <summary>
        /// 设置修改相关数据
        /// </summary>
        /// <param name="model"></param>
        /// <param name="currentUserId"></param>
        public static void SetModifyField(object model, string currentUserId)
        {
            var type = model.GetType();
            var pinfos = type.GetProperties();
            if (pinfos.Any(a => a.Name.Equals("LastModifiedBy")))
            {
                var info = pinfos.FirstOrDefault(a => a.Name.Equals("LastModifiedBy"));
                if (info != null) info.SetValue(model, currentUserId, null);
            }
            if (pinfos.Any(a => a.Name.Equals("LastModifiedTime")))
            {
                var info = pinfos.FirstOrDefault(a => a.Name.Equals("LastModifiedTime"));
                if (info != null) info.SetValue(model, DateTime.Now, null);
            }
            if (pinfos.Any(a => a.Name.Equals("ModifyBy")))
            {
                var info = pinfos.FirstOrDefault(a => a.Name.Equals("ModifyBy"));
                if (info != null) info.SetValue(model, currentUserId, null);
            }
            if (pinfos.Any(a => a.Name.Equals("ModifyTime")))
            {
                var info = pinfos.FirstOrDefault(a => a.Name.Equals("ModifyTime"));
                if (info != null) info.SetValue(model, DateTime.Now, null);
            }
        }

        /// <summary>
        /// 设置删除相关数据
        /// </summary>
        /// <param name="model"></param>
        /// <param name="currentUserId"></param>
        public static void SetDeleteField(object model, string currentUserId)
        {
            var type = model.GetType();
            var pinfos = type.GetProperties();
            if (pinfos.Any(a => a.Name.Equals("DeletedBy")))
            {
                var info = pinfos.FirstOrDefault(a => a.Name.Equals("DeletedBy"));
                if (info != null) info.SetValue(model, currentUserId, null);
            }
            if (pinfos.Any(a => a.Name.Equals("DeletedTime")))
            {
                var info = pinfos.FirstOrDefault(a => a.Name.Equals("DeletedTime"));
                if (info != null) info.SetValue(model, DateTime.Now, null);
            }
            if (pinfos.Any(a => a.Name.Equals("DeleteBy")))
            {
                var info = pinfos.FirstOrDefault(a => a.Name.Equals("DeleteBy"));
                if (info != null) info.SetValue(model, currentUserId, null);
            }
            if (pinfos.Any(a => a.Name.Equals("DeleteTime")))
            {
                var info = pinfos.FirstOrDefault(a => a.Name.Equals("DeleteTime"));
                if (info != null) info.SetValue(model, DateTime.Now, null);
            }
        }

        #endregion
    }
}
